﻿// Handles application state
(function (winjs, applicationController, vmLocator) {
    "use strict";

    //Handles checkpoint event to persist state
    winjs.Application.oncheckpoint = function (args) {
        args.setPromise(onSave());
    };

    //Handles resuming event since is not exposed by applicaton object
    Windows.UI.WebUI.WebUIApplication.addEventListener("resuming", onAppResuming);

    //Persists state
    function onSave() {
        return new winjs.Promise(function (complete) {
            winjs.Application.sessionState.app = {
                state: applicationController.serialize(),
                navigationHistory: winjs.Navigation.history,
                viewModels: {}
            };

            //Serializes services that implements serialize function
            var j = 0;
            applicationController.services.forEach(function (service) {
                if (service.serialize !== undefined) {
                    var state = service.serialize();
                    var serviceKey = "service" + j;
                    winjs.Application.sessionState.app[serviceKey] = state;
                }
            });

            //Invokes serialize for each viewmodel
            for (var key in vmLocator.viewModels) {
                var vm = vmLocator.viewModels[key];
                if (vm && vm.serialize) {
                    winjs.Application.sessionState.app.viewModels[key] = vm.serialize();
                }
            }

            complete();
        });
    }

    //Reload state
    function load() {
        if (winjs.Application.sessionState != null) {
            var savedState = winjs.Application.sessionState.app;
            applicationController.hydrate(savedState.state);
            //Retrieve navigation history
            winjs.Navigation.history = savedState.navigationHistory;
            winjs.Navigation.history.current.initialPlaceholder = true;

            //De-Serializes services that implements serialize function
            var j = 0;
            applicationController.services.forEach(function (service) {
                if (service.hydrate !== undefined) {
                    var serviceKey = "service" + j;
                    var serviceState = winjs.Application.sessionState.app[serviceKey];
                    service.hydrate(serviceState);
                }
            });

            //Allows each viewmodel to rehydrate themselves
            for (var key in savedState.viewModels) {
                var vm = vmLocator.viewModels[key];
                if (vm === undefined) {
                    //Instatiates viewmodel, using [name]ViewModel convention
                    vm = vmLocator.createViewModelForTarget(key);
                    if (vm.hydrate) {
                        vm.hydrate(savedState);
                    }
                }
            }

            winjs.Application.sessionState.app = null;
        }
    }

    //Post a resuming message to application
    function onAppResuming() {
        applicationController.services.forEach(function (service) {
            if (service.onAppResuming !== undefined) {
                service.onAppResuming();
            }
        });

        for (var key in vmLocator.viewModels) {
            var vm = vmLocator.viewModels[key];
            if (vm && vm.onAppResuming) {
                vm.onAppResuming();
            }
        }
    }

    winjs.Namespace.define("MvvmStack.Application", {
        state: {
            load: load,
        }
    });

})(WinJS, Demo.Application.ApplicationController, Demo.ViewModelLocator);